"""
Author: yangyuqi yangyuqi@datagrand.com
Date: 2024-12-16 13:28:33
@LastEditors: yangyuqi yangyuqi@datagrand.com
@LastEditTime: 2024/12/30 12:20
FilePath: /simple-util-py/simpleutil/rich_content/nodes/__init__.py
Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
"""

from enum import Enum
from typing import Optional

from simpleutil.classes import get_dimension
from simpleutil.core import ToolClass
from simpleutil.json import json_str_configuration
from simpleutil.randoms import generate_string


class Node:
    pass


class ContentNode(Node):
    fontSize: Optional[str]
    color: Optional[str]
    text: Optional[str]

    def __init__(
        self,
        font_size: Optional[str] = None,
        color: Optional[str] = None,
        text: Optional[str] = "",
    ):
        self.text = str(text if text is not None else "")
        self.fontSize = font_size
        self.color = color


class StructNode(Node):
    id: str
    type: str
    children: list[Node]

    def __init__(self, type: str):
        self.id = generate_string()
        self.type = type
        self.children = []

    def add_child(self, child: Node):
        self.children.append(child)

    def add_children(self, children: list[Node]):
        for child in children:
            self.children.append(child)


class TextNode(StructNode):
    def __init__(
        self,
        type: str,
        font_size: Optional[str] = None,
        color: Optional[str] = None,
        text: Optional[str] = "",
    ):
        super().__init__(type=type)
        self.add_child(ContentNode(font_size=font_size, color=color, text=text))


class UrlNode(StructNode):
    def __init__(
        self,
        url: str,
        font_size: Optional[str] = None,
        color: Optional[str] = None,
        text: str = "",
    ):
        super().__init__(type="a")
        self.url = url
        self.add_child(ContentNode(font_size=font_size, color=color, text=text))


class TableDataAttributesInfo:
    rowspan: Optional[str]

    def __init__(self, rowspan: Optional[str] = None):
        self.rowspan = rowspan


class TableDataNode(StructNode):
    background: Optional[str]
    attributes: Optional[TableDataAttributesInfo]

    def __init__(
        self,
        text: Optional[str] = None,
        font_size: Optional[str] = None,
        color: Optional[str] = None,
        background: Optional[str] = None,
        attributes: Optional[TableDataAttributesInfo] = None,
    ):
        super().__init__(type="td")
        self.background = background
        self.attributes = attributes
        self.add_child(TextNode(type="p", font_size=font_size, color=color, text=text))


class TableRowNode(StructNode):
    def __init__(
        self,
        values: list = [],
        font_size: Optional[str] = None,
        color: Optional[str] = None,
        background: Optional[str] = None,
    ):
        super().__init__(type="tr")
        self.completed = False
        self.td_background = background
        self.td_font_size = font_size
        self.td_color = color
        self.add_table_data_nodes(values=values)

    def add_table_data_nodes(
        self,
        values: list = [],
        font_size: Optional[str] = None,
        color: Optional[str] = None,
        background: Optional[str] = None,
    ):
        if values:
            for v in values:
                self.add_child(
                    TableDataNode(
                        text=v,
                        font_size=font_size if font_size else self.td_font_size,
                        color=color if color else self.td_color,
                        background=background if background else self.td_background,
                    )
                )


class TableNode(StructNode):
    colSizes: Optional[list[int]]
    marginLeft: Optional[int]

    def __init__(
        self,
        titles: list = [],
        titles_background: Optional[str] = None,
        titles_font_size: Optional[str] = None,
        titles_color: Optional[str] = None,
        strict_cols: bool = False,
        least_rows: int = 0,
        col_sizes: Optional[list[int]] = None,
        margin_left: Optional[int] = None,
    ):
        super().__init__(type="table")
        if titles:
            self.strict_cols = strict_cols
            self.cols = len(titles)
            self.add_child(
                TableRowNode(
                    values=titles,
                    font_size=titles_font_size,
                    background=titles_background,
                    color=titles_color,
                )
            )
        else:
            self.strict_cols = False
            self.cols = 0
        self.least_rows = least_rows
        self.colSizes = col_sizes
        self.marginLeft = margin_left
        self.completed = False

    def add_rows(
        self,
        data,
        font_size: Optional[str] = None,
        color: Optional[str] = None,
        background: Optional[str] = None,
    ):
        if not self.check_complete():
            return self
        dimension = get_dimension(data)
        if dimension == 1:
            self.add_child(
                TableRowNode(
                    data[0 : self.cols] if self.strict_cols else data,
                    font_size=font_size,
                    background=background,
                    color=color,
                )
            )
        elif dimension == 2:
            for tr in data:
                self.add_rows(tr, font_size=font_size, color=color, background=background)
        return self

    def add_row_nodes(self, row_nodes: list[Node]):
        if self.check_complete():
            self.add_children(row_nodes)
        return self

    def add_row_by_data_nodes(self, data_nodes: list[Node]):
        if self.check_complete():
            row_node = TableRowNode()
            self.add_child(row_node)
            row_node.add_children(data_nodes)
        return self

    def check_complete(self) -> bool:
        if self.completed:
            # TODO:log
            return False
        else:
            return True

    def complete(
        self,
        fill_font_size: Optional[str] = None,
        fill_color: Optional[str] = None,
        fill_background: Optional[str] = None,
        fill_text: Optional[str] = "",
    ):
        if not self.check_complete():
            return
        remain = self.least_rows - len(self.children)
        while remain > 0:
            remain -= 1
            self.add_child(
                TableRowNode(
                    values=[fill_text for i in range(self.cols)],
                    font_size=fill_font_size,
                    background=fill_background,
                    color=fill_color,
                )
            )
        self.completed = True


class LayoutTypeEnum(Enum):
    TWO = ("[][]", "1-1", ["50%", "50%"])
    THREE = ("[][][]", "1-1-1", ["33%", "33%", "33%"])
    THREE_SEVEN = ("[][    ]", "3-7", ["30%", "70%"])
    SEVEN_THREE = ("[    ][]", "7-3", ["70%", "30%"])
    TOW_SIDES = ("[][ ][]", "1-2-1", ["25%", "50%", "25%"])

    def __init__(self, description: str, layout: str, ratios=[]):
        self.description = description
        self.layout = layout
        self.ratios = ratios


class LayoutChildNode(StructNode):
    width: Optional[str]

    def __init__(
        self,
        width: Optional[str] = None,
    ):
        super().__init__(type="layout_child")
        self.width = width


class LayoutNode(StructNode):
    layout: str

    def __init__(
        self,
        layout: LayoutTypeEnum = LayoutTypeEnum.TWO,
    ):
        super().__init__(type="layout")
        self.layout = layout.layout
        widths = layout.ratios
        for width in widths:
            self.add_child(LayoutChildNode(width=width))

    def get_layout_child(self, index) -> LayoutChildNode:
        return self.children[index]


class BaseContent(ToolClass, list[Node]):
    def __init__(self):
        self.__json_str_config__ = json_str_configuration(kv_spaces_num=0, ensure_ascii=False)

    def add_text(
        self,
        type,
        font_size: Optional[str] = None,
        color: Optional[str] = None,
        text: Optional[str] = None,
    ) -> TextNode:
        node = TextNode(text=text, font_size=font_size, type=type, color=color)
        self.append(node)
        return node

    def add_url(self, url) -> UrlNode:
        pass

    def add_table(
        self,
        titles: list = [],
        titles_background: Optional[str] = None,
        titles_font_size: Optional[str] = None,
        titles_color: Optional[str] = None,
        strict_cols: bool = False,
        least_rows: int = 0,
        col_sizes: Optional[list[int]] = None,
        margin_left: Optional[int] = None,
    ) -> TableNode:
        node = TableNode(
            titles=titles,
            titles_background=titles_background,
            titles_font_size=titles_font_size,
            titles_color=titles_color,
            strict_cols=strict_cols,
            least_rows=least_rows,
            col_sizes=col_sizes,
            margin_left=margin_left,
        )
        self.append(node)
        return node

    def add_layout(self, layout: LayoutTypeEnum) -> LayoutNode:
        node = LayoutNode(layout=layout)
        self.append(node)
        return node

    def add_empty_line(self) -> None:
        self.append(TextNode(type="p"))
